﻿using System;
using UnityEngine;

namespace RootMotion.FinalIK
{
	// Token: 0x0200004A RID: 74
	[Serializable]
	public class IKSolverLimb : IKSolverTrigonometric
	{
		// Token: 0x06000365 RID: 869 RVA: 0x0000445C File Offset: 0x0000265C
		public IKSolverLimb()
		{
		}

		// Token: 0x06000366 RID: 870 RVA: 0x0000447B File Offset: 0x0000267B
		public IKSolverLimb(AvatarIKGoal goal)
		{
			this.goal = goal;
		}

		// Token: 0x06000367 RID: 871 RVA: 0x000044A1 File Offset: 0x000026A1
		public void MaintainRotation()
		{
			if (!base.initiated)
			{
				return;
			}
			this.maintainRotation = this.bone3.transform.rotation;
			this.maintainRotationFor1Frame = true;
		}

		// Token: 0x06000368 RID: 872 RVA: 0x000044CC File Offset: 0x000026CC
		public void MaintainBend()
		{
			if (!base.initiated)
			{
				return;
			}
			this.animationNormal = this.bone1.GetBendNormalFromCurrentRotation();
			this.maintainBendFor1Frame = true;
		}

		// Token: 0x06000369 RID: 873 RVA: 0x0002AA54 File Offset: 0x00028C54
		public override void OnInitiateVirtual()
		{
			this.defaultRootRotation = this.root.rotation;
			if (this.bone1.transform.parent != null)
			{
				this.parentDefaultRotation = Quaternion.Inverse(this.defaultRootRotation) * this.bone1.transform.parent.rotation;
			}
			if (this.bone3.rotationLimit != null)
			{
				this.bone3.rotationLimit.Disable();
			}
			this.bone3DefaultRotation = this.bone3.transform.rotation;
			Vector3 vector = Vector3.Cross(this.bone2.transform.position - this.bone1.transform.position, this.bone3.transform.position - this.bone2.transform.position);
			if (vector != Vector3.zero)
			{
				this.bendNormal = vector;
			}
			this.animationNormal = this.bendNormal;
			if (this.goal == AvatarIKGoal.LeftHand || this.goal == AvatarIKGoal.RightHand)
			{
				this.StoreAxisDirections();
			}
		}

		// Token: 0x0600036A RID: 874 RVA: 0x0002AB88 File Offset: 0x00028D88
		public override void OnUpdateVirtual()
		{
			if (this.IKPositionWeight > 0f)
			{
				this.bendModifierWeight = Mathf.Clamp(this.bendModifierWeight, 0f, 1f);
				this.maintainRotationWeight = Mathf.Clamp(this.maintainRotationWeight, 0f, 1f);
				this._bendNormal = this.bendNormal;
				this.bendNormal = this.GetModifiedBendNormal();
			}
			if (this.maintainRotationWeight * this.IKPositionWeight > 0f)
			{
				this.bone3RotationBeforeSolve = ((!this.maintainRotationFor1Frame) ? this.bone3.transform.rotation : this.maintainRotation);
				this.maintainRotationFor1Frame = false;
			}
		}

		// Token: 0x0600036B RID: 875 RVA: 0x0002AC40 File Offset: 0x00028E40
		public override void OnPostSolveVirtual()
		{
			if (this.IKPositionWeight > 0f)
			{
				this.bendNormal = this._bendNormal;
			}
			if (this.maintainRotationWeight * this.IKPositionWeight > 0f)
			{
				this.bone3.transform.rotation = Quaternion.Slerp(this.bone3.transform.rotation, this.bone3RotationBeforeSolve, this.maintainRotationWeight * this.IKPositionWeight);
			}
		}

		// Token: 0x0600036C RID: 876 RVA: 0x0002ACB8 File Offset: 0x00028EB8
		public void StoreAxisDirections()
		{
			IKSolverLimb.AxisDirection axisDirection = new IKSolverLimb.AxisDirection(Vector3.zero, new Vector3(-1f, 0f, 0f));
			IKSolverLimb.AxisDirection axisDirection2 = new IKSolverLimb.AxisDirection(new Vector3(0.5f, 0f, -0.2f), new Vector3(-0.5f, -1f, 1f));
			IKSolverLimb.AxisDirection axisDirection3 = new IKSolverLimb.AxisDirection(new Vector3(-0.5f, -1f, -0.2f), new Vector3(0f, 0.5f, -1f));
			IKSolverLimb.AxisDirection axisDirection4 = new IKSolverLimb.AxisDirection(new Vector3(-0.5f, -0.5f, 1f), new Vector3(-1f, -1f, -1f));
			this.axisDirections = new IKSolverLimb.AxisDirection[]
			{
				axisDirection,
				axisDirection2,
				axisDirection3,
				axisDirection4
			};
		}

		// Token: 0x0600036D RID: 877 RVA: 0x0002ADB4 File Offset: 0x00028FB4
		public Vector3 GetModifiedBendNormal()
		{
			float num = this.bendModifierWeight;
			if (num <= 0f)
			{
				return this.bendNormal;
			}
			switch (this.bendModifier)
			{
			case IKSolverLimb.BendModifier.Animation:
				if (!this.maintainBendFor1Frame)
				{
					this.MaintainBend();
				}
				this.maintainBendFor1Frame = false;
				return Vector3.Lerp(this.bendNormal, this.animationNormal, num);
			case IKSolverLimb.BendModifier.Target:
			{
				Quaternion b = this.IKRotation * Quaternion.Inverse(this.bone3DefaultRotation);
				return Quaternion.Slerp(Quaternion.identity, b, num) * this.bendNormal;
			}
			case IKSolverLimb.BendModifier.Parent:
			{
				if (this.bone1.transform.parent == null)
				{
					return this.bendNormal;
				}
				Quaternion lhs = this.bone1.transform.parent.rotation * Quaternion.Inverse(this.parentDefaultRotation);
				return Quaternion.Slerp(Quaternion.identity, lhs * Quaternion.Inverse(this.defaultRootRotation), num) * this.bendNormal;
			}
			case IKSolverLimb.BendModifier.Arm:
			{
				if (this.bone1.transform.parent == null)
				{
					return this.bendNormal;
				}
				if (this.goal == AvatarIKGoal.LeftFoot || this.goal == AvatarIKGoal.RightFoot)
				{
					if (!Warning.logged)
					{
						base.LogWarning("Trying to use the 'Arm' bend modifier on a leg.");
					}
					return this.bendNormal;
				}
				Vector3 vector = (this.IKPosition - this.bone1.transform.position).normalized;
				vector = Quaternion.Inverse(this.bone1.transform.parent.rotation * Quaternion.Inverse(this.parentDefaultRotation)) * vector;
				if (this.goal == AvatarIKGoal.LeftHand)
				{
					vector.x = -vector.x;
				}
				for (int i = 1; i < this.axisDirections.Length; i++)
				{
					this.axisDirections[i].dot = Mathf.Clamp(Vector3.Dot(this.axisDirections[i].direction, vector), 0f, 1f);
					this.axisDirections[i].dot = Interp.Float(this.axisDirections[i].dot, InterpolationMode.InOutQuintic);
				}
				Vector3 vector2 = this.axisDirections[0].axis;
				for (int j = 1; j < this.axisDirections.Length; j++)
				{
					vector2 = Vector3.Slerp(vector2, this.axisDirections[j].axis, this.axisDirections[j].dot);
				}
				if (this.goal == AvatarIKGoal.LeftHand)
				{
					vector2.x = -vector2.x;
					vector2 = -vector2;
				}
				Vector3 vector3 = this.bone1.transform.parent.rotation * Quaternion.Inverse(this.parentDefaultRotation) * vector2;
				if (num >= 1f)
				{
					return vector3;
				}
				return Vector3.Lerp(this.bendNormal, vector3, num);
			}
			case IKSolverLimb.BendModifier.Goal:
			{
				if (this.bendGoal == null)
				{
					if (!Warning.logged)
					{
						base.LogWarning("Trying to use the 'Goal' Bend Modifier, but the Bend Goal is unassigned.");
					}
					return this.bendNormal;
				}
				Vector3 vector4 = Vector3.Cross(this.bendGoal.position - this.bone1.transform.position, this.IKPosition - this.bone1.transform.position);
				if (vector4 == Vector3.zero)
				{
					return this.bendNormal;
				}
				if (num >= 1f)
				{
					return vector4;
				}
				return Vector3.Lerp(this.bendNormal, vector4, num);
			}
			default:
				return this.bendNormal;
			}
		}

		// Token: 0x0400022B RID: 555
		public AvatarIKGoal goal;

		// Token: 0x0400022C RID: 556
		public IKSolverLimb.BendModifier bendModifier;

		// Token: 0x0400022D RID: 557
		[Range(0f, 1f)]
		public float maintainRotationWeight;

		// Token: 0x0400022E RID: 558
		[Range(0f, 1f)]
		public float bendModifierWeight = 1f;

		// Token: 0x0400022F RID: 559
		public Transform bendGoal;

		// Token: 0x04000230 RID: 560
		public bool maintainBendFor1Frame;

		// Token: 0x04000231 RID: 561
		public bool maintainRotationFor1Frame;

		// Token: 0x04000232 RID: 562
		public Quaternion defaultRootRotation;

		// Token: 0x04000233 RID: 563
		public Quaternion parentDefaultRotation;

		// Token: 0x04000234 RID: 564
		public Quaternion bone3RotationBeforeSolve;

		// Token: 0x04000235 RID: 565
		public Quaternion maintainRotation;

		// Token: 0x04000236 RID: 566
		public Quaternion bone3DefaultRotation;

		// Token: 0x04000237 RID: 567
		public Vector3 _bendNormal;

		// Token: 0x04000238 RID: 568
		public Vector3 animationNormal;

		// Token: 0x04000239 RID: 569
		public IKSolverLimb.AxisDirection[] axisDirections = new IKSolverLimb.AxisDirection[0];

		// Token: 0x0200004B RID: 75
		[Serializable]
		public enum BendModifier
		{
			// Token: 0x0400023B RID: 571
			Animation,
			// Token: 0x0400023C RID: 572
			Target,
			// Token: 0x0400023D RID: 573
			Parent,
			// Token: 0x0400023E RID: 574
			Arm,
			// Token: 0x0400023F RID: 575
			Goal
		}

		// Token: 0x0200004C RID: 76
		[Serializable]
		public struct AxisDirection
		{
			// Token: 0x0600036E RID: 878 RVA: 0x000044F2 File Offset: 0x000026F2
			public AxisDirection(Vector3 direction, Vector3 axis)
			{
				this.direction = direction.normalized;
				this.axis = axis.normalized;
				this.dot = 0f;
			}

			// Token: 0x04000240 RID: 576
			public Vector3 direction;

			// Token: 0x04000241 RID: 577
			public Vector3 axis;

			// Token: 0x04000242 RID: 578
			public float dot;
		}
	}
}
